package com.yunhe.authority.service.authority.impl;

import com.yunhe.authority.domain.authority.*;
import com.yunhe.authority.repository.authority.MenuRepository;
import com.yunhe.authority.repository.authority.RoleRepository;
import com.yunhe.authority.repository.authority.StationRepository;
import com.yunhe.authority.repository.authority.impl.RoleDao;
import com.yunhe.authority.repository.authority.impl.UserDao;
import com.yunhe.authority.service.authority.*;
import com.yunhe.authority.util.MyHeaderUtil;
import com.yunhe.common.filter.ServerContextHolder;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.DatabaseProcessException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.util.QueryUtil;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.common.util.CollectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 角色Service
 * @author liuronglei
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    RoleRepository roleRepository;
    @Autowired
    MenuRepository menuRepository;
    @Autowired
    UserService userService;
    @Autowired
    StationService stationService;
    @Autowired
    MenuService menuService;
    @Autowired
    StationRepository stationRepository;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private MyHeaderUtil headerUtil;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;

    private static Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);

    /**
     * 角色对象处理和判断
     * @param role 角色对象
     */
    private void processBeforeSave(Role role)
            throws ArgumentErrorException, UniqueConstraintsException {
        //判断角色编号、角色标题是否为空
        if (StringUtil.isEmpty(role.getName())
                || StringUtil.isEmpty(role.getTitle())) {
            throw new ArgumentErrorException("角色编号、角色标题不能为空");
        }
        //判断角色编号是否已存在
//        Role roleByName = this.findByName(role.getName());
//        if (roleByName != null) {
//            if (role.getId() == null || roleByName.getId().longValue() != role.getId().longValue()) {
//                throw new UniqueConstraintsException("该角色已被使用");
//            }
//        }
//        if (role.getId() == null && role.getTitle() != null) {
//            Role roleByTitle = roleRepository.findByTitle(role.getTitle());
//            if (roleByTitle != null) {
//                throw new UniqueConstraintsException("该角色名称已存在");
//            }
//        }
    }

    private void updateParent(Role role, Long parentId) throws ObjectNotFoundException {
        if (role != null) {
            roleRepository.unbindParentRoleById(role.getId());
        }
        if (parentId != null && parentId != -1) {
            Role parent = findByRoleId(parentId);
            if (parent == null) {
                throw new ObjectNotFoundException("找不到ID为" + parentId + "的父角色");
            }
            roleRepository.bindChildRoleById(parentId, role.getId());
        }
    }

    /**
     * 对菜单列表进行排序
     * @param menuList 菜单列表
     */
    private void sortMenus(List<Menu> menuList) {
        if (menuList != null && menuList.size() > 0) {
            Collections.sort(menuList);
            for (Menu menu : menuList) {
                if (menu.getChildren() != null && menu.getChildren().size() > 0) {
                    sortMenus(menu.getChildren());
                }
            }
        }
    }

    /**
     * 为用户菜单列表构建树形
     * @param resultMap 要构建树形的菜单Map
     * @param allMenu 全部菜单列表
     */
    private void buildMenuTreeForUser(Map<Long, Menu> resultMap, List<Menu> allMenu) {
        for (int i = allMenu.size() - 1; i >= 0; i--) {
            if (!resultMap.containsKey(allMenu.get(i).getId())) {
                allMenu.remove(i);
            } else {
                if (allMenu.get(i).getChildren() != null) {
                    buildMenuTreeForUser(resultMap, allMenu.get(i).getChildren());
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Role createRole(Long parentId, Long stationId, Long firmId, Role role)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {
        role.setId(null);

        User user = headerUtil.getHeaderUser();
        BackUser headerBackUser = headerUtil.getHeaderBackUser();
        if (user != null) {
            role.setCreator(user.getTitle());
        }else if(headerBackUser != null){
            role.setCreator(headerBackUser.getTitle());
        }

        role.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

        if (parentId != null) {
            Role parent = findByRoleId(parentId);
            role.setLevel(parent.getLevel() + 1);
        } else {
            role.setLevel(1);
        }


        processBeforeSave(role);
        Role newRole = roleRepository.save(role);

        if (parentId != null) {
            //绑定父关系
            updateParent(newRole, parentId);
        }
        //后台系统添加
        if (firmId == null && stationId == null) {
            Role existRole = roleRepository.findRolesByDefaultFirmIdAndTitle(999999999L, role.getTitle());
            if (existRole != null) {
                throw new UniqueConstraintsException(role.getTitle() + "已存在");
            }
            //这里代表这个角色是管理后台创建的
            roleRepository.bindDefaultFirm(newRole.getId(), 999999999L);
        }

        //单位添加
        if (firmId != null) {
            Role existRole = roleRepository.findRoleByFirmIdAndTitle(firmId, role.getTitle());
            if (existRole != null) {
                throw new UniqueConstraintsException(role.getTitle() + "已存在");
            }
            //绑定单位
            roleRepository.bindFirm(newRole.getId(), firmId);
        }

        //园区添加
        if (stationId != null) {
            Role existRole = roleRepository.findRoleByStationIdAndTitle(stationId, role.getTitle());
            if (existRole != null) {
                throw new UniqueConstraintsException(role.getTitle() + "已存在");
            }
            //绑定项目
            roleRepository.roleBindStation(newRole.getId(), stationId);
        }
        return newRole;
    }

    /**
     * 根据id删除角色
     * @param roleId 角色ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void deleteRole(Long roleId) throws ArgumentErrorException {
        List<User> list = (List<User>)roleRepository.findBindUsersById(roleId);
        if (list == null || list.size() == 0) {
            roleRepository.deleteById(roleId);
        } else {
            throw new ArgumentErrorException("该角色下有用户不能删除");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void deleteRoleByIds(String ids) throws ArgumentErrorException {
        String[] strings = ids.split(",");
        for (String id : strings) {
            Role role = findByRoleId(Long.valueOf(id));
            if(role != null && role.isInitRole()){
                throw new ArgumentErrorException("当前角色名为："+role.getTitle()+"的角色为后台管理平台初始化角色不能删除！");
            }
            deleteRole(Long.valueOf(id));
        }
    }

    /**
     * 更新角色
     * @param role 要更新的角色对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Role updateRole(Role role)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {

        Role role1 = findByRoleId(role.getId());
        if(role1 != null && role1.isInitRole()){
            throw new ArgumentErrorException("当前角色名为："+role.getTitle()+"的角色为后台管理平台初始化角色不能编辑！");
        }
        processBeforeSave(role);

        Optional<Role> roleOptional = roleRepository.findById(role.getId());
        if (!roleOptional.isPresent()) {
            throw new ObjectNotFoundException("找不到ID为" + role.getId() + "的角色");
        }

        String projectCode = ServerContextHolder.getContext().getProjectCode();
        //这边是带上园区的id进行查询重名
        if (StringUtils.isNotEmpty(projectCode)) {
            logger.info("当前正在更新角色的园区id为：{}，角色名为：{}", projectCode, role.getTitle());
            Role existRole = roleRepository.findRoleByStationIdAndTitle(Long.valueOf(projectCode), role.getTitle());
            if (existRole != null && !existRole.getId().equals(role.getId())) {
                throw new UniqueConstraintsException(role.getTitle() + "已存在");
            }
        }

        Role oldRole = roleOptional.get();
        Optional.ofNullable(role.getActivity()).ifPresent(oldRole::setActivity);
        Optional.ofNullable(role.getName()).ifPresent(oldRole::setName);
        Optional.ofNullable(role.getTitle()).ifPresent(oldRole::setTitle);
        Optional.ofNullable(role.getDescription()).ifPresent(oldRole::setDescription);
        Optional.ofNullable(role.getCreator()).ifPresent(oldRole::setCreator);

        return roleRepository.save(oldRole);
    }

    /**
     * 更新角色
     * @param roleId 角色ID
     * @param name 角色编号
     * @param title 角色标题
     * @param activity 是否可用
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Role updateRole(Long roleId,
                           String name,
                           String title,
                           String activity)
            throws ArgumentErrorException, ObjectNotFoundException, UniqueConstraintsException {
        Role role = this.findByRoleId(roleId);
        if (role == null) {
            throw new ObjectNotFoundException("找不到ID为" + roleId + "的角色");
        }
        Optional.ofNullable(name).ifPresent(role::setName);
        Optional.ofNullable(title).ifPresent(role::setTitle);
        if (activity != null) {
            if (activity.equals(false)) {
                List<User> list = (List) roleRepository.findActiveUsersById(roleId);
                if (list == null || list.size() == 0) {
                    role.setActivity(activity);
                } else {
                    throw new ArgumentErrorException("该角色下有用户不能删除");
                }
            } else {
                role.setActivity(activity);
            }
        }
        processBeforeSave(role);
        return roleRepository.save(role);
    }

    /**
     * 根据ID获得角色对象
     * @param roleId 角色ID
     */
    @Override
    public Role findByRoleId(Long roleId) {
        return roleRepository.findById(roleId).orElse(null);
    }

    /**
     * 根据角色编号获得角色对象
     * @param name 角色编号
     */
    @Override
    public Role findByName(String name) {
        return roleRepository.findByName(name);
    }

    @Override
    public Iterable<Role> findRole(Long userId, String name, String title, PageParam pageParam) {
        List<Role> list = (List)userService.findRolesByUserId(userId);
        Role role = list.get(0);
        if (role.getLevel() == 0) {
            return roleRepository.findRolesByRootId(role.getId());
        } else {
            return roleRepository.findRolesById(role.getId());
        }
    }

    private List<Role> sortByLevel(Iterable<Role> roles) {
        List<Role> list = (List)roles;
        Collections.sort(list);
        return list;
    }

    @Override
    public Iterable<Role> findRole(Long userId) {
        List<Role> list = (List<Role>)userService.findRolesByUserId(userId);
        Role role = list.get(0);
        Iterable<Role> results;
        if (role.getLevel().intValue() == 0) {
            results = roleRepository.findRolesByRootId(role.getId());
        } else {
            results = roleRepository.findRolesById(role.getId());
        }
        return sortByLevel(results);
    }

    @Override
    public Iterable<Role> findRoles(Long userId, String name, String title, PageParam pageParam) {
        List<Role> list = (List)userService.findRolesByUserId(userId);
        if (list != null && list.size() > 0) {
            Role role = list.get(0);
            if (role.getLevel() == 0) {
                return findRoles(role.getLevel(), null, name, title, pageParam);
            } else {
                return findRoles(role.getLevel(), true, name, title, pageParam);
            }
        } else {
            return findRoles(name, title, pageParam);
        }
    }

    @Override
    public Iterable<Role> getRoles(Long userId, String name, String title, PageParam pageParam) {
        try {
            List<Role> list1 = (List<Role>) findRoles(userId, name, title, new PageParam());
            List<Role> list2 = (List<Role>) findRole(userId);
            List<Role> list = new ArrayList<>();
            for (Role role : list1) {
                for (Role r : list2) {
                    if (role.getId().longValue() == r.getId()) {
                        list.add(role);
                    }
                }
            }
            List<Role> roles = sortByLevel(list);
            if (QueryUtil.needPaging(pageParam)) {
                Pageable pageable = QueryUtil.getPageRequest(pageParam);
                List<Role> pages = new ArrayList<>();
                long page = pageable.getOffset();
                int size = pageable.getPageSize();
                for (int i = 0; i < roles.size(); i++) {
                    if (i >= page && i < page + size) {
                        pages.add(roles.get(i));
                    }
                }
                return new PageImpl<>(pages, pageable, roles.size());
            } else {
                return roles;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Iterable<Role> findRoles(Long userId, String title, PageParam pageParam) {
        try {
            List<Role> list = (List) userService.findRolesByUserId(userId);
            if (list != null && list.size() > 0) {
                Role role = list.get(0);
                if (role.getLevel() == 0) {
                    return findRoles(role.getLevel(), null, title, pageParam);
                } else {
                    return findRoles(role.getLevel(), true, title, pageParam);
                }
            } else {
                return findRoles("", title, pageParam);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public Iterable<Role> findRoles(Integer level, Boolean activity, String title, PageParam pageParam) {
        Iterable<Role> results;
        Boolean activityValue = false;
        if (activity != null) {
            activityValue = activity;
        }
        List<String> defaultSortParam = new ArrayList<>();
        defaultSortParam.add("-createTime");
        if (QueryUtil.needPaging(pageParam)) {
            if (pageParam.getSort() == null) {
                pageParam.setSort(defaultSortParam);
            }
            Pageable pageable = QueryUtil.getPageRequest(pageParam);
            if (StringUtils.isEmpty(title) && activity == null) {
                results = roleRepository.findAll(pageable);
            } else {
                Page<Role> page = roleRepository.findByTitleLike(title, pageable);
                List<Role> content = page.getContent();
                List<Role> result = new ArrayList<>();
                if (activity != null) {
                    for (Role role : content) {
                        if (role.getActivity().equals(activityValue) && role.getLevel() >= level) {
                            result.add(role);
                        }
                    }
                    results = new PageImpl<>(result, pageable, result.size());
                } else {
                    results = page;
                }
            }
        } else {
            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
            if (sort == null) {
                sort = QueryUtil.getSort(defaultSortParam);
            }
            if (StringUtils.isEmpty(title)) {
                try {
                    List<Role> list = (List) roleRepository.findAll(sort);
                    List<Role> result = new ArrayList<>();
                    if (activity != null) {
                        for (Role role : list) {
                            if (role.getActivity().equals(activityValue) && role.getLevel() >= level) {
                                result.add(role);
                            }
                        }
                        results = result;
                    } else {
                        results = list;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            } else {
                List<Role> list = (List)roleRepository.findByTitleContaining(title);
                List<Role> result = new ArrayList<>();
                if (activity != null) {
                    for (Role role : list) {
                        if (role.getActivity().equals(activityValue)) {
                            result.add(role);
                        }
                    }
                    results = result;
                } else {
                    results = list;
                }
            }
        }
        return results;
    }

    public Iterable<Role> findRoles(Integer level, Boolean activity, String name, String title, PageParam pageParam) {
        Iterable<Role> results;
        Boolean activityValue = false;
        if (activity != null) {
            activityValue = activity;
        }
        List<String> defaultSortParam = new ArrayList<>();
        defaultSortParam.add("-createTime");
        if (QueryUtil.needPaging(pageParam)) {
            if (pageParam.getSort() == null) {
                pageParam.setSort(defaultSortParam);
            }
            Pageable pageable = QueryUtil.getPageRequest(pageParam);
            if (StringUtils.isEmpty(name) && StringUtils.isEmpty(title) && activity == null) {
                results = roleRepository.findAll(pageable);
            } else {
                Page<Role> page = roleRepository.findByNameLikeOrTitleLike(name, title, pageable);
                List<Role> content = page.getContent();
                List<Role> result = new ArrayList<>();
                if (activity != null) {
                    for (Role role : content) {
                        if (role.getActivity().equals(activityValue) && role.getLevel() >= level) {
                            result.add(role);
                        }
                    }
                    results = new PageImpl<>(result, pageable, result.size());
                } else {
                    results = page;
                }
            }
        } else {
            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
            if (sort == null) {
                sort = QueryUtil.getSort(defaultSortParam);
            }
            if (StringUtils.isEmpty(name) && StringUtils.isEmpty(title)) {
                try {
                    List<Role> list = (List) roleRepository.findAll(sort);
                    List<Role> result = new ArrayList<>();
                    if (activity != null) {
                        for (Role role : list) {
                            if (role.getActivity().equals(activityValue) && role.getLevel() >= level) {
                                result.add(role);
                            }
                        }
                        results = result;
                    } else {
                        results = list;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            } else {
                List<Role> list = (List)roleRepository.findByNameLikeOrTitleLike(name, title, sort);
                List<Role> result = new ArrayList<>();
                if (activity != null) {
                    for (Role role : list) {
                        if (role.getActivity().equals(activityValue)) {
                            result.add(role);
                        }
                    }
                    results = result;
                } else {
                    results = list;
                }
            }
        }
        return results;
    }

    /**
     * 根据条件获得所有用户对象
     * @param name 角色编号
     * @param title 角色标题
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<Role> findRoles(String name, String title, PageParam pageParam) {

        Iterable<Role> results;
        List<String> defaultSortParam = new ArrayList<>();
        defaultSortParam.add("-createTime");
        if (QueryUtil.needPaging(pageParam)) {
            if (pageParam.getSort() == null) {
                pageParam.setSort(defaultSortParam);
            }
            pageParam.setPage(pageParam.getPage() - 1);
            Pageable pageable = QueryUtil.getPageRequest(pageParam);
            if (StringUtils.isEmpty(name) && StringUtils.isEmpty(title)) {
                results = roleRepository.findAll(pageable);
            } else {
                results = roleRepository.findByNameLikeOrTitleLike(name, title, pageable);
            }
        } else {
            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
            if (sort == null) {
                sort = QueryUtil.getSort(defaultSortParam);
            }
            if (StringUtils.isEmpty(name) && StringUtils.isEmpty(title)) {
                results = roleRepository.findAll(sort);
            } else {
                results = roleRepository.findByNameLikeOrTitleLike(name, title, sort);
            }
        }
        //查询关联用户列表
        results.forEach(role -> role.setNumberOfAssociatedUsers(roleRepository.findUsersNumberById(role.getId())));
        return results;
    }

    @Override
    public Page<Role> findAllRoles(String keywords, PageParam pageParam) {
        return roleDao.findAllRoles(keywords, pageParam);
    }

    /**
     * 根据用户ID获得角色列表
     * @param userId 用户ID
     */
    @Override
    public Iterable<Role> findRolesByUserId(Long userId) {
        return roleRepository.findRolesByUserId(userId);
    }

    /**
     * 根据角色ID获得菜单列表
     * @param roleId 角色ID
     */
    @Override
    public Iterable<Menu> findMenusByRoleId(Long roleId) {
        List<Menu> list = (List<Menu>)menuRepository.findMenusByRoleId(roleId);
//        if (list != null) {
//            Map<Long, Menu> resultMap = new HashMap<>();
//            for (Menu menu : list) {
//                resultMap.put(menu.getId(), null);
//            }
//            list = (List<Menu>)menuService.findMenus();
//            buildMenuTreeForUser(resultMap, list);
//        }
//        sortMenus(list);
        return list;
    }

    @Override
    public Iterable<Menu> findHasMenusByRoleId(Long roleId) {
        List<Menu> list = (List<Menu>)menuRepository.findHasMenusByRoleId(roleId);
        if (list != null) {
            Map<Long, Menu> resultMap = new HashMap<>();
            for (Menu menu : list) {
                resultMap.put(menu.getId(), null);
            }
            list = (List<Menu>)menuService.findMenus();
            buildMenuTreeForUser(resultMap, list);
        }
        sortMenus(list);
        return list;
    }

    /**
     * 根据角色ID获得菜单列表
     * @param roleId 角色ID
     */
    @Override
    public Iterable<Menu> findAppMenusByRoleId(Long roleId) {
        List<Menu> list = (List)menuRepository.findAppMenusByRoleId(roleId);
        if (list != null) {
            Map<Long, Menu> resultMap = new HashMap<>();
            for (Menu menu : list) {
                resultMap.put(menu.getId(), null);
            }
            list = (List<Menu>)menuService.findMenus();
            buildMenuTreeForUser(resultMap, list);
        }
        sortMenus(list);
        return list;
    }

    @Override
    public Iterable<Menu> findHasAppMenusByRoleId(Long roleId) {
        return menuRepository.findHasAppMenusByRoleId(roleId);
    }

    /**
     * 根据角色ID获得菜单列表
     * @param roleId 角色ID
     * @param userId
     */
    @Override
    public Iterable<User> findUsersByRoleId(Long roleId, Long userId) {
        return userService.findUsersByRoleId(roleId, userId);
    }

    /**
     * 角色绑定菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindMenu(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindMenu(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindHasMenu(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindHasMenu(roleId, menuId);
    }

    /**
     * 角色绑定App菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindAppMenu(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindAppMenu(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindHasAppMenu(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindHasAppMenu(roleId, menuId);
    }

    /**
     * 解绑菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindMenu(Long roleId, Long menuId) {
        roleRepository.unbindMenu(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindAppMenu(Long roleId, Long menuId) {
        roleRepository.unbindAppMenu(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindHasMenu(Long roleId, Long menuId) {
        roleRepository.unbindHasMenu(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindHasAppMenu(Long roleId, Long menuId) {
        roleRepository.unbindHasAppMenu(roleId, menuId);
    }

    /**
     * 批量更新菜单绑定
     * @param roleId 角色ID
     * @param menuIdList 菜单ID列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllMenus(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(menuIdList)) {
            for (Long menuId : menuIdList) {
                roleRepository.bindMenu(roleId, menuId);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateAppMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllAppMenus(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(menuIdList)) {
            for (Long menuId : menuIdList) {
                roleRepository.bindAppMenu(roleId, menuId);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateHasMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllHasMenus(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(menuIdList)) {
            for (Long menuId : menuIdList) {
                roleRepository.bindHasMenu(roleId, menuId);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateHasAppMenu(Long roleId, List<Long> menuIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllHasAppMenus(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(menuIdList)) {
            for (Long menuId : menuIdList) {
                roleRepository.bindHasAppMenu(roleId, menuId);
            }
        }
    }

    @Override
    public Iterable<User> findUsersById(Long id) {
        return roleRepository.findUsersById(id);
    }

    @Override
    public Page<User> findUsersByIdAndCondition(Long id, String keywords, PageParam pageParam) {
        return userDao.findUsersById(id, keywords, pageParam);
    }

    /**
     * 角色绑定App菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindStation(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindStation(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void bindHasStation(Long roleId, Long menuId)
            throws DatabaseProcessException {
        roleRepository.bindHasStation(roleId, menuId);
    }

    /**
     * 解绑菜单
     * @param roleId 角色ID
     * @param menuId 菜单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindStation(Long roleId, Long menuId) {
        roleRepository.unbindStation(roleId, menuId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void unbindHasStation(Long roleId, Long menuId) {
        roleRepository.unbindHasStation(roleId, menuId);
    }

    /**
     * 批量更新电站绑定
     * @param roleId 角色ID
     * @param stationIdList 电站ID列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateStation(Long roleId, List<Long> stationIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllStations(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(stationIdList)) {
            for (Long stationId : stationIdList) {
                roleRepository.bindStation(roleId, stationId);
            }
        }
    }

    /**
     * 批量更新电站绑定
     * @param roleId 角色ID
     * @param stationIdList 电站ID列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateHasStation(Long roleId, List<Long> stationIdList)
            throws DatabaseProcessException {
        //先解绑
        roleRepository.unbindAllHasStations(roleId);
        //再绑定
        if (CollectionUtil.isNotEmpty(stationIdList)) {
            for (Long stationId : stationIdList) {
                roleRepository.bindHasStation(roleId, stationId);
            }
        }
    }

    @Override
    public Role getParentRole(Long id) {
        return roleRepository.getParentRole(id);
    }

    @Override
    public Iterable<User> findActiveUsersById(Long id) {
        return roleRepository.findActiveUsersById(id);
    }

    @Override
    public Boolean findExists(Role role1, Role role2) {
        return roleRepository.findExists(role1.getId(), role2.getId());
    }

    @Override
    public List<Role> findRolesByStationIdOrFirmId(Long stationId, Long firmId) {
        List<Role> roleList = new ArrayList<>();

        //如果都为空则是查询后台角色,firmId=999999999,这边写死
        if (stationId == null && firmId == null) {
            roleList = (List<Role>)roleRepository.findRolesByDefaultFirmId(999999999L);
        }

        if (stationId != null) {
            roleList = (List<Role>)roleRepository.findRolesByStationId(stationId);
        }
        if (firmId != null) {
            roleList = (List<Role>)roleRepository.findRolesByFirmId(firmId);
        }

        return roleList;
    }

    @Override
    public Page<Role> findRolesByStationIdOrFirmIdForPage(Long stationId, Long firmId, String keywords, PageParam pageParam) {
        Page<Role> rolePage = new PageImpl<>(new ArrayList<Role>());

        //如果都为空则是查询管理后台角色,999999999,这边写死
        if (stationId == null && firmId == null) {
            rolePage = roleDao.findRolesByDefaultFirmId(999999999L, keywords, pageParam);
        }

        if (stationId != null) {
            rolePage = roleDao.findRolesByStationId(stationId, keywords, pageParam);
        }
        if (firmId != null) {
            rolePage = roleDao.findRolesByFirmId(firmId, keywords, pageParam);
        }

        return rolePage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void roleBindMenus(Long roleId, String menuIds, String systemMenuCategory)
            throws ArgumentErrorException, ObjectNotFoundException {
        if (roleId == null) {
            throw new ArgumentErrorException("请选择角色！");
        }
        if (roleRepository.findRolesById(roleId) == null) {
            throw new ObjectNotFoundException("未找到该角色，请重新加载！");
        }

        if (StringUtils.isEmpty(menuIds)) {
            roleRepository.unbindAllMenusAndSystemMenuCategory(roleId,systemMenuCategory);
        } else {
            //先解绑再绑定
            roleRepository.unbindAllMenusAndSystemMenuCategory(roleId,systemMenuCategory);
            String[] strings = menuIds.split(",");
            for (String id : strings) {
                roleRepository.bindMenu(roleId, Long.valueOf(id));
            }
        }
    }

    @Override
    public Iterable<Role> findByRoleIds(List<Long> roleIds) {

        return roleRepository.findByIds(roleIds);
    }

    @Override
    public Iterable<Role> findByUserId(Long userId, Long stationId, Long firmId) {
        if(stationId != null){
            return roleRepository.findByUserIdAndStationId(userId,stationId);
        }else if(firmId != null){
            return roleRepository.findByUserIdAndFirmId(userId,firmId);
        }
        return null;
    }

    @Override
    public Iterable<Role> findByUserId(Long userId, Long stationId, Long firmId, String roleType) {
        roleType = ".*"+roleType+".*";
        if(stationId != null){
            return roleRepository.findByUserIdAndStationId(userId,stationId,roleType);
        }else if(firmId != null){
            return roleRepository.findByUserIdAndFirmId(userId,firmId,roleType);
        }
        return null;
    }

    @Override
    public ProejctRoleOrg getRoleByLoginUser(Long stationId, Long firmId) throws ArgumentErrorException {
        ProejctRoleOrg proejctRoleOrg = new ProejctRoleOrg();
        User headerUser = headerUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("该用户登录信息已过期，请重新登录");
        }
        proejctRoleOrg.setUserId(headerUser.getId());
        proejctRoleOrg.setUserPhone(headerUser.getPhone());
        proejctRoleOrg.setUserTitle(headerUser.getTitle());
        if(stationId != null && firmId == null){
            User user = userService.findByUserIdAndStationId(headerUser.getId(), stationId);
            if(user == null){
                throw new ArgumentErrorException("该用户在当前的项目的状态为禁用！");
            }
            //查询园区项目的角色
            List<Role> roles = (List<Role>) roleRepository.findByUserIdAndStationId(headerUser.getId(), stationId);
            if(CollectionUtil.isNotEmpty(roles)){
                List<Long> topicPaths = roles.stream().filter(role-> role.getId()!=null).map(Role::getId).collect(Collectors.toList());
                List<String> collect = topicPaths.stream().map(topicPath -> {
                    return String.valueOf(topicPath);
                }).collect(Collectors.toList());
                String roleIds = String.join(",", collect);
                List<String> roleNameList = roles.stream().filter(role-> role.getId()!=null).map(Role::getName).collect(Collectors.toList());
                String roleNames = String.join(",",roleNameList);
                proejctRoleOrg.setRoleIds(roleIds);
                proejctRoleOrg.setRoleTitles(roleNames);
            }
            //查询用户园区的归属组织
            List<Organization> orgs = (List<Organization>) organizationService.findBelongOrgByUserId(headerUser.getId(), stationId, null);
            if(CollectionUtil.isNotEmpty(orgs)){
                Organization org = orgs.get(0);
                proejctRoleOrg.setOrgId(org.getId());
                proejctRoleOrg.setOrgTitle(org.getTitle());
            }
            List<Organization> synergyOrgs = (List<Organization>) organizationService.findSynergyOrgByUserId(headerUser.getId(), stationId, null);
            //记录当前登录人所选的项目信息标记项目类型
            userService.updateLastProejct(headerUser.getId(),stationId,"station");
            //记录当前所选择项目以及归属部门
            setOrgId(headerUser.getId(),proejctRoleOrg.getOrgId(),"station");
            //记录当前所选择项目以及协同部门
            if(CollectionUtil.isNotEmpty(synergyOrgs)){
                List<String> collect = synergyOrgs.stream().map(synergyOrg->{
                    return String.valueOf(synergyOrg.getId());
                }).collect(Collectors.toList());
                setSynergyOrgId(headerUser.getId(),String.join(",", collect),"station");
            }
        }else if(stationId == null && firmId != null){
            //todo 目前没有单位账号 先不做逻辑处理
        }
        return proejctRoleOrg;
    }

    @Override
    public List<Role> findByEmployeeId(Long employeeId) {
        return (List<Role>)roleRepository.findRoleByEmployeeId(employeeId);
    }

    private void setSynergyOrgId(Long userId, String orgId, String projectType) {
        redisClient.set("SynergyOrg:"+userId, String.valueOf(orgId)+"-"+projectType);
    }

    private void setOrgId(Long userId, Long orgId, String projectType) {
        redisClient.set("Org:"+userId, String.valueOf(orgId)+"-"+projectType);
    }
}
